package com.stm.bi.report.productTrend;

import com.stm.bi.core.util.DateUtils;
import com.stm.bi.core.util.ETLUtils;
import com.stm.bi.core.util.SqlUtils;
import com.stm.bi.dto.query.*;
import com.stm.bi.enums.ParamType;
import com.stm.bi.model.Chart;
import com.stm.bi.model.DatatablePage;
import com.stm.bi.model.RowData;
import com.stm.bi.model.Title;
import com.stm.framework.core.context.UserHolder;
import com.stm.framework.core.util.HumpUtil;
import com.stm.framework.core.util.StringUtil;
import com.stm.framework.dbcp.JdbcService;
import com.stm.framework.dto.Response;
import com.stm.saas.api.IndexRemoteService;
import com.stm.saas.api.ProductAssortmentRemoteService;
import com.stm.saas.api.ProductCategoryRemoteService;
import com.stm.saas.api.ProductStyleRemoteService;
import com.stm.saas.api.PolicyDetailRemoteService;
import com.stm.saas.dto.query.ProductAssortmentListQry;
import com.stm.saas.dto.query.PolicyDetailByLevelBandQry;
import com.stm.saas.dto.query.ProductCategoryListQry;
import com.stm.saas.dto.query.ProductStylePageQry;
import com.stm.saas.dto.vo.IndexVO;
import com.stm.saas.dto.vo.ProductAssortmentVO;
import com.stm.saas.dto.vo.ProductCategoryVO;
import com.stm.saas.dto.vo.ProductStyleQueryVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static com.stm.bi.constant.IndexConstants.*;
import static com.stm.bi.constant.PlanConstants.TYPE_WEEK;
import static com.stm.bi.constant.ProductTrendConstants.*;
import static com.stm.bi.report.productTrend.ProductDataQueryExe.DELAY;
import static com.stm.bi.report.productTrend.ProductDataQueryExe.getProdCodeAndName;

@Component
public class DigestibilityReportQueryExe {

    @Resource
    private ProductDataQueryExe productDataQueryExe;
    @Resource
    private JdbcService jdbcService;
    @Resource
    private IndexRemoteService indexRemoteService;
    @Resource
    private ProductCategoryRemoteService productCategoryRemoteService;
    @Resource
    private ProductAssortmentRemoteService productAssortmentRemoteService;
    @Resource
    private ProductStyleRemoteService productStyleRemoteService;
    @Resource
    private PolicyDetailRemoteService policyDetailRemoteService;

    public Chart<List<List<Object>>> digestibilityProcessChart(ChartReportQry reportQry) {
        // 根据categoryLevel判断使用不同的处理逻辑
        Integer categoryLevel = getCategoryLevelFromReportQry(reportQry);

        if (categoryLevel == null || categoryLevel == 0) {
            // 原有逻辑：使用ads_base_product_multi_sales表
            return digestibilityProcessChartOriginal(reportQry);
        } else if (categoryLevel >= 1 && categoryLevel <= 7) {
            // 新逻辑：使用ads_res_policy_sales和ads_res_policy_inventory表
            return digestibilityProcessChartPolicy(reportQry);
        } else {
            throw new IllegalArgumentException("不支持的categoryLevel值: " + categoryLevel);
        }
    }

    /**
     * 从ChartReportQry中获取categoryLevel
     */
    private Integer getCategoryLevelFromReportQry(ChartReportQry reportQry) {
        String categoryLevelStr = reportQry.getCategoryLevel();
        return convertCategoryLevel(categoryLevelStr);
    }

    /**
     * 将categoryLevel字符串转换为Integer
     *
     * @param categoryLevel 分类等级字符串
     * @return 转换后的整数值，"style"返回null，其它尝试转换
     */
    private Integer convertCategoryLevel(String categoryLevel) {
        if (categoryLevel == null || categoryLevel.isEmpty() || "style".equals(categoryLevel)) {
            return null;  // 走原有逻辑
        }

        try {
            return Integer.parseInt(categoryLevel);
        } catch (NumberFormatException e) {
            // 转换失败时返回null，避免报错
            return null;
        }
    }

    /**
     * 【原有逻辑】售罄率过程图表
     */
    public Chart<List<List<Object>>> digestibilityProcessChartOriginal(ChartReportQry reportQry) {

        Chart<List<List<Object>>> chart = new Chart<>();
        List<List<Object>> datas = new ArrayList<>();
        List<List<Object>> total = new ArrayList<>();

        Long deptId = reportQry.getDeptId();

        List<GroupField> groupFields = List.of(
                GroupField.of(QTY_FIELD, "sum"),
                GroupField.of(POSITIVE_SALES_VOLUME_FIELD_NAME, "sum"),
                GroupField.of(SPECIAL_SALES_VOLUME_FIELD_NAME, "sum")
        );

        List<String> dateList = DateUtils.getHistoryDateList(reportQry.getStartDate(), reportQry.getEndDate(), reportQry.getDateType().getValue(), DELAY);

        if (dateList.isEmpty()) {
            return chart;
        }

        String startDate = dateList.getFirst();
        String endDate = dateList.getLast();

        DimensionDataGroupQry qry = new DimensionDataGroupQry()
                .setOrgNo(UserHolder.getLoginUser().getOrgNo())
                .setSalesType(reportQry.getSalesType())
                .setDeptId(reportQry.getDeptId())
                .setDateType(reportQry.getDateType().getValue())
                .setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupFields(groupFields)
                .setGroupBy(List.of(DATE_FIELD));

        setDigestibilitySqlQry(reportQry.getParams(), qry, DIGESTIBILITY_STYLE);

        String sql = SqlUtils.buildSql(qry, "ads_base_product_multi_sales");
        List<Map> data = jdbcService.selectList(sql, new Object[]{});

        data = productDataQueryExe.selectInventoryData(qry, null, data);


        chart.getItems().add(POSITIVE_SALES_VOLUME_INDEX_NAME);
        chart.getItems().add(SPECIAL_SALES_VOLUME_INDEX_NAME);

        chart.getItems().add(DIGESTIBILITY_INDEX_NAME);


        double qtySum = 0;
        double inventoryQty = 0;
        double positiveSalesVolumeSum = 0;
        double specialSalesVolumeSum = 0;
        double inventorySum = 0;

        String s = productDataQueryExe.selectMaxInventoryDate(startDate, endDate, reportQry.getDateType().getValue());

        inventorySum = data.stream()
                .filter(d -> d.get(DATE_FIELD).equals(s))
                .map(d -> ((BigDecimal) d.get(INVENTORY_FIELD)))
                .filter(Objects::nonNull)
                .mapToDouble(BigDecimal::doubleValue)
                .sum();

        if (TYPE_WEEK.equals(reportQry.getDateType().getValue())) {
            List<Map> beforeQty = getBeforeQty(deptId, startDate, qry);

            inventoryQty += beforeQty.stream()
                    .map(d -> ((BigDecimal) d.get(QTY_FIELD)))
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal::add)
                    .orElse(BigDecimal.ZERO)
                    .doubleValue();
        }


        for (String date : dateList) {
            List<Object> row = new ArrayList<>();

            List<Map> maps = data.stream()
                    .filter(d -> d.get(DATE_FIELD).equals(date))
                    .toList();

            double positiveSalesVolume = maps.stream()
                    .map(d -> (BigDecimal) d.get(POSITIVE_SALES_VOLUME_FIELD_NAME))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            positiveSalesVolumeSum += positiveSalesVolume;

            double specialSalesVolume = maps.stream()
                    .map(d -> (BigDecimal) d.get(SPECIAL_SALES_VOLUME_FIELD_NAME))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            specialSalesVolumeSum += specialSalesVolume;

            double qty = maps.stream()
                    .map(d -> (BigDecimal) d.get(QTY_FIELD))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            qtySum += qty;
            inventoryQty += qty;

            double inventory = maps.stream()
                    .map(d -> (BigDecimal) d.get(INVENTORY_FIELD))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            if (date.compareTo(s) >= 0) {
                inventory = inventorySum;
            }

            BigDecimal digestibility;
            // 【图表售罄率计算】累计销量 ÷ (库存 + 累计销量) × 100%
            if (inventory + inventoryQty > 0 && inventoryQty > 0) {
                // inventoryQty为累计销量，inventory为当前库存
                digestibility = BigDecimal.valueOf(inventoryQty * 100 / (inventory + inventoryQty)).setScale(2, RoundingMode.HALF_UP);
            } else {
                digestibility = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);  // 累计销量为0时设为0
            }

            row.add(DateUtils.getReportDateName(date, reportQry.getDateType().getValue()));
            row.add(BigDecimal.valueOf(positiveSalesVolume));
            row.add(BigDecimal.valueOf(specialSalesVolume));
            row.add(digestibility);

            datas.add(row);
        }

        BigDecimal digestibility = BigDecimal.valueOf(inventorySum + inventoryQty != 0 && inventoryQty > 0 ? (inventoryQty * 100 / (inventorySum + inventoryQty)) : 0).setScale(2, RoundingMode.HALF_UP);

        total.add(Arrays.asList(TOTAL_QTY_INDEX_NAME, BigDecimal.valueOf(qtySum), null, 0));
        total.add(Arrays.asList(POSITIVE_SALES_VOLUME_INDEX_NAME, BigDecimal.valueOf(positiveSalesVolumeSum), null, 0));
        total.add(Arrays.asList(SPECIAL_SALES_VOLUME_INDEX_NAME, BigDecimal.valueOf(specialSalesVolumeSum), null, 0));
        total.add(Arrays.asList(DIGESTIBILITY_INDEX_NAME, digestibility + "%", null, 1));

        chart.setDatas(datas);
        chart.setExtend(total);

        return chart;
    }

    /**
     * 【新逻辑】政策售罄率过程图表 - 使用ads_res_policy_sales表
     */
    public Chart<List<List<Object>>> digestibilityProcessChartPolicy(ChartReportQry reportQry) {
        Chart<List<List<Object>>> chart = new Chart<>();
        List<List<Object>> datas = new ArrayList<>();
        List<List<Object>> total = new ArrayList<>();

        Long deptId = reportQry.getDeptId();
        Integer categoryLevel = getCategoryLevelFromReportQry(reportQry);

        List<GroupField> groupFields = List.of(
                GroupField.of(QTY_FIELD, "sum"),
                GroupField.of(POSITIVE_SALES_VOLUME_FIELD_NAME, "sum"),
                GroupField.of(SPECIAL_SALES_VOLUME_FIELD_NAME, "sum")
        );

        List<String> dateList = DateUtils.getHistoryDateList(reportQry.getStartDate(), reportQry.getEndDate(), reportQry.getDateType().getValue(), DELAY);

        if (dateList.isEmpty()) {
            return chart;
        }

        String startDate = dateList.getFirst();
        String endDate = dateList.getLast();

        DimensionDataGroupQry qry = new DimensionDataGroupQry()
                .setOrgNo(UserHolder.getLoginUser().getOrgNo())
                .setSalesType(reportQry.getSalesType())
                .setDeptId(reportQry.getDeptId())
                .setDateType(reportQry.getDateType().getValue())
                .setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupFields(groupFields)
                .setGroupBy(List.of(DATE_FIELD));

        // 设置政策层级条件
        Map<String, Object> otherConditions = new HashMap<>();
        otherConditions.put("level", categoryLevel);

        // 适配原有筛选条件
        setPolicyDigestibilitySqlQry(reportQry.getParams(), otherConditions, categoryLevel);
        qry.setOtherConditions(otherConditions);

        String sql = SqlUtils.buildSql(qry, "ads_res_policy_sales");
        List<Map> data = jdbcService.selectList(sql, new Object[]{});

        data = selectPolicyInventoryData(qry, null, data);

        chart.getItems().add(POSITIVE_SALES_VOLUME_INDEX_NAME);
        chart.getItems().add(SPECIAL_SALES_VOLUME_INDEX_NAME);
        chart.getItems().add(DIGESTIBILITY_INDEX_NAME);

        double qtySum = 0;
        double inventoryQty = 0;
        double positiveSalesVolumeSum = 0;
        double specialSalesVolumeSum = 0;
        double inventorySum = 0;

        String s = selectMaxInventoryDatePolicy(startDate, endDate, reportQry.getDateType().getValue());

        inventorySum = data.stream()
                .filter(d -> d.get(DATE_FIELD).equals(s))
                .map(d -> ((BigDecimal) d.get(INVENTORY_FIELD)))
                .filter(Objects::nonNull)
                .mapToDouble(BigDecimal::doubleValue)
                .sum();

        if (TYPE_WEEK.equals(reportQry.getDateType().getValue())) {
            List<Map> beforeQty = getBeforeQtyPolicy(deptId, startDate, qry, categoryLevel);

            inventoryQty += beforeQty.stream()
                    .map(d -> ((BigDecimal) d.get(QTY_FIELD)))
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal::add)
                    .orElse(BigDecimal.ZERO)
                    .doubleValue();
        }

        for (String date : dateList) {
            List<Object> row = new ArrayList<>();

            List<Map> maps = data.stream()
                    .filter(d -> d.get(DATE_FIELD).equals(date))
                    .toList();

            double positiveSalesVolume = maps.stream()
                    .map(d -> (BigDecimal) d.get(POSITIVE_SALES_VOLUME_FIELD_NAME))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            positiveSalesVolumeSum += positiveSalesVolume;

            double specialSalesVolume = maps.stream()
                    .map(d -> (BigDecimal) d.get(SPECIAL_SALES_VOLUME_FIELD_NAME))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            specialSalesVolumeSum += specialSalesVolume;

            double qty = maps.stream()
                    .map(d -> (BigDecimal) d.get(QTY_FIELD))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            qtySum += qty;
            inventoryQty += qty;

            double inventory = maps.stream()
                    .map(d -> (BigDecimal) d.get(INVENTORY_FIELD))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            if (date.compareTo(s) >= 0) {
                inventory = inventorySum;
            }

            BigDecimal digestibility;
            // 【政策售罄率计算】累计销量 ÷ (库存 + 累计销量) × 100%
            if (inventory + inventoryQty > 0 && inventoryQty > 0) {
                digestibility = BigDecimal.valueOf(inventoryQty * 100 / (inventory + inventoryQty)).setScale(2, RoundingMode.HALF_UP);
            } else {
                digestibility = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
            }

            row.add(DateUtils.getReportDateName(date, reportQry.getDateType().getValue()));
            row.add(BigDecimal.valueOf(positiveSalesVolume));
            row.add(BigDecimal.valueOf(specialSalesVolume));
            row.add(digestibility);

            datas.add(row);
        }

        BigDecimal digestibility = BigDecimal.valueOf(inventorySum + inventoryQty != 0 && inventoryQty > 0 ? (inventoryQty * 100 / (inventorySum + inventoryQty)) : 0).setScale(2, RoundingMode.HALF_UP);

        total.add(Arrays.asList(TOTAL_QTY_INDEX_NAME, BigDecimal.valueOf(qtySum), null, 0));
        total.add(Arrays.asList(POSITIVE_SALES_VOLUME_INDEX_NAME, BigDecimal.valueOf(positiveSalesVolumeSum), null, 0));
        total.add(Arrays.asList(SPECIAL_SALES_VOLUME_INDEX_NAME, BigDecimal.valueOf(specialSalesVolumeSum), null, 0));
        total.add(Arrays.asList(DIGESTIBILITY_INDEX_NAME, digestibility + "%", null, 1));

        chart.setDatas(datas);
        chart.setExtend(total);

        return chart;
    }


    public Chart<List<List<Object>>> digestibilityProcessDetailChart(DetailChartReportQry reportQry) {
        // 根据categoryLevel判断使用不同的处理逻辑
        Integer categoryLevel = getCategoryLevelFromReportQry(reportQry);

        if (categoryLevel == null || categoryLevel == 0) {
            // 原有逻辑：使用ads_base_product_multi_sales表
            return digestibilityProcessDetailChartOriginal(reportQry);
        } else if (categoryLevel >= 1 && categoryLevel <= 7) {
            // 新逻辑：使用ads_res_policy_sales和ads_res_policy_inventory表
            return digestibilityProcessDetailChartPolicy(reportQry);
        } else {
            throw new IllegalArgumentException("不支持的categoryLevel值: " + categoryLevel);
        }
    }

    /**
     * 【原有逻辑】售罄率过程详细图表
     */
    public Chart<List<List<Object>>> digestibilityProcessDetailChartOriginal(DetailChartReportQry reportQry) {

        String indexId = reportQry.getParams().stream().filter(item -> ParamType.INDEX.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(String.valueOf(QTY_INDEX_ID));

        Chart<List<List<Object>>> chart = new Chart<>();
        Long deptId = reportQry.getDeptId();
        List<String> dateList = DateUtils.getHistoryDateList(reportQry.getStartDate(), reportQry.getEndDate(), reportQry.getDateType().getValue(), DELAY);

        String startDate = dateList.getFirst();
        String endDate = dateList.getLast();

        if (dateList.isEmpty()) {
            return chart;
        }

        Response<IndexVO> indexResp = indexRemoteService.selectById(Long.parseLong(indexId));
        IndexVO index = indexResp.getData();
        List<String> codeAndName = getProdCodeAndName(DIGESTIBILITY_STYLE);
        String code = codeAndName.getFirst();
        String name = codeAndName.getLast();

        List<GroupField> groupFields = new ArrayList<>(Arrays.asList(
                new GroupField().setFieldName(QTY_FIELD).setGroupType("sum"),
                new GroupField().setFieldName(POSITIVE_SALES_VOLUME_FIELD_NAME).setGroupType("sum"),
                new GroupField().setFieldName(SPECIAL_SALES_VOLUME_FIELD_NAME).setGroupType("sum")
        ));

        DimensionDataGroupQry qry = new DimensionDataGroupQry()
                .setDeptId(reportQry.getDeptId())
                .setSalesType(reportQry.getSalesType())
                .setDateType(reportQry.getDateType().getValue())
                .setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupFields(groupFields)
                .setGroupBy(List.of(code, name));

        setDigestibilitySqlQry(reportQry.getParams(), qry, DIGESTIBILITY_STYLE);
        List<Map> data;

        String s = productDataQueryExe.selectMaxInventoryDate(startDate, endDate, reportQry.getDateType().getValue());

        List<Map> qtyTotalMap = new ArrayList<>();

        if (DIGESTIBILITY_INDEX_ID.equals(Long.parseLong(indexId))) {

            String sql = SqlUtils.buildSql(qry, "ads_base_product_multi_sales");
            List<Map> maps = jdbcService.selectList(sql, new Object[]{});

            if (TYPE_WEEK.equals(reportQry.getDateType().getValue())) {

                qtyTotalMap = getBeforeQty(deptId, startDate, qry);
            }

            qry.setStartDate(s)
                    .setEndDate(s);

            List<Map> lastMap = productDataQueryExe.selectInventoryData(qry, code, new ArrayList<>());

            data = digestibilitySummarize(code, maps, lastMap, qtyTotalMap);

        } else if (OPENING_INVENTORY_INDEX_ID.equals(Long.parseLong(indexId))) {

            qry.setEndDate(qry.getStartDate());
            data = productDataQueryExe.selectInventoryData(qry, code, new ArrayList<>());
            qry.setDeptId(deptId);

        } else if (INVENTORY_INDEX_ID.equals(Long.parseLong(indexId))) {

            qry.setStartDate(s)
                    .setEndDate(s);
            data = productDataQueryExe.selectInventoryData(qry, code, new ArrayList<>());
            qry.setDeptId(deptId);

        } else {
            String sql = SqlUtils.buildSql(qry, "ads_base_product_multi_sales");
            List<Map> maps = jdbcService.selectList(sql, new Object[]{});
            
            // 对非售罄率指标也进行产品汇总，避免同一产品出现多条记录
            data = aggregateDataByProduct(code, maps, index.getFieldName());
        }

        // 根据索引ID确定排序字段
        String sortFieldName = getSortFieldName(index.getId(), index.getFieldName());
        
        // 优化排序逻辑，处理null值避免报错
        Comparator<Map> comparator = Comparator.comparing(
            (Map m) -> Optional.ofNullable((BigDecimal) m.get(sortFieldName))
                               .orElse(BigDecimal.ZERO)
        );
        
        if (reportQry.getLimit() > 0) {
            data.sort(comparator.reversed());
        } else {
            data.sort(comparator);
        }

        List<Map> finalMaps = data.subList(0, Math.min(data.size(), Math.abs(reportQry.getLimit())));

        List<String> codes = finalMaps.stream()
                .map(m -> (String) m.get(code))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        qry.setStartDate(dateList.getFirst())
                .setEndDate(dateList.getLast())
                .setGroupBy(Arrays.asList(code, DATE_FIELD))
                .setDeptId(reportQry.getDeptId());

        if (qry.getOtherConditions() == null) {
            qry.setOtherConditions(new HashMap<>());
        }
        qry.getOtherConditions().put(code, codes);
        String sql = SqlUtils.buildSql(qry, "ads_base_product_multi_sales");

        List<Map> dataMap = jdbcService.selectList(sql, new Object[]{});

        dataMap = productDataQueryExe.selectInventoryData(qry, code, dataMap, dateList);

        chart = digestibilityChart(index, code, name, dataMap, finalMaps, dateList, reportQry.getDateType().getValue(), qtyTotalMap);

        return chart;
    }

    /**
     * 【新逻辑】政策售罄率过程详细图表 - 使用ads_res_policy_sales表
     */
    public Chart<List<List<Object>>> digestibilityProcessDetailChartPolicy(DetailChartReportQry reportQry) {

        String indexId = reportQry.getParams().stream().filter(item -> ParamType.INDEX.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(String.valueOf(QTY_INDEX_ID));

        Chart<List<List<Object>>> chart = new Chart<>();
        Long deptId = reportQry.getDeptId();
        Integer categoryLevel = getCategoryLevelFromReportQry(reportQry);
        List<String> dateList = DateUtils.getHistoryDateList(reportQry.getStartDate(), reportQry.getEndDate(), reportQry.getDateType().getValue(), DELAY);

        String startDate = dateList.getFirst();
        String endDate = dateList.getLast();

        if (dateList.isEmpty()) {
            return chart;
        }

        Response<IndexVO> indexResp = indexRemoteService.selectById(Long.parseLong(indexId));
        IndexVO index = indexResp.getData();

        // 使用政策维度字段
        String code = "policy_id";          // 政策ID字段
        String name = "policy_name";        // 政策名称字段

        List<GroupField> groupFields = new ArrayList<>(Arrays.asList(
                new GroupField().setFieldName(QTY_FIELD).setGroupType("sum"),
                new GroupField().setFieldName(POSITIVE_SALES_VOLUME_FIELD_NAME).setGroupType("sum"),
                new GroupField().setFieldName(SPECIAL_SALES_VOLUME_FIELD_NAME).setGroupType("sum")
        ));

        DimensionDataGroupQry qry = new DimensionDataGroupQry()
                .setOrgNo(UserHolder.getLoginUser().getOrgNo())
                .setSalesType(reportQry.getSalesType())
                .setDeptId(reportQry.getDeptId())
                .setDateType(reportQry.getDateType().getValue())
                .setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupFields(groupFields)
                .setGroupBy(List.of(code, name));

        // 设置政策层级条件
        Map<String, Object> otherConditions = new HashMap<>();
        otherConditions.put("level", categoryLevel);

        // 适配原有筛选条件
        setPolicyDigestibilitySqlQry(reportQry.getParams(), otherConditions, categoryLevel);
        qry.setOtherConditions(otherConditions);

        List<Map> data = new ArrayList<>();

        String s = selectMaxInventoryDatePolicy(startDate, endDate, reportQry.getDateType().getValue());

        List<Map> qtyTotalMap = new ArrayList<>();

        if (DIGESTIBILITY_INDEX_ID.equals(Long.parseLong(indexId))) {

            String sql = SqlUtils.buildSql(qry, "ads_res_policy_sales");
            List<Map> maps = jdbcService.selectList(sql, new Object[]{});

            if (TYPE_WEEK.equals(reportQry.getDateType().getValue())) {
                qtyTotalMap = getBeforeQtyPolicy(deptId, startDate, qry, categoryLevel);
            }

            qry.setStartDate(s)
                    .setEndDate(s);

            List<Map> lastMap = selectPolicyInventoryData(qry, code, new ArrayList<>());

            data = digestibilitySummarize(code, maps, lastMap, qtyTotalMap);

        } else if (OPENING_INVENTORY_INDEX_ID.equals(Long.parseLong(indexId))) {

            qry.setEndDate(qry.getStartDate());
            data = selectPolicyInventoryData(qry, code, new ArrayList<>());
            qry.setDeptId(deptId);

        } else if (INVENTORY_INDEX_ID.equals(Long.parseLong(indexId))) {

            qry.setStartDate(s)
                    .setEndDate(s);
            data = selectPolicyInventoryData(qry, code, new ArrayList<>());
            qry.setDeptId(deptId);

        } else {
            String sql = SqlUtils.buildSql(qry, "ads_res_policy_sales");
            List<Map> maps = jdbcService.selectList(sql, new Object[]{});
            
            // 对非售罄率指标也进行产品汇总，避免同一产品出现多条记录
            data = aggregateDataByProduct(code, maps, index.getFieldName());
        }

        // 根据索引ID确定排序字段
        String sortFieldName = getSortFieldName(index.getId(), index.getFieldName());
        
        // 优化排序逻辑，处理null值避免报错
        Comparator<Map> comparator = Comparator.comparing(
            (Map m) -> Optional.ofNullable((BigDecimal) m.get(sortFieldName))
                               .orElse(BigDecimal.ZERO)
        );
        
        if (reportQry.getLimit() > 0) {
            data.sort(comparator.reversed());
        } else {
            data.sort(comparator);
        }

        List<Map> finalMaps = data.subList(0, Math.min(data.size(), Math.abs(reportQry.getLimit())));

        List<Long> policyIds = finalMaps.stream()
                .map(m -> (Long) m.get(code))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        qry.setStartDate(dateList.getFirst())
                .setEndDate(dateList.getLast())
                .setGroupBy(Arrays.asList(code, DATE_FIELD))
                .setDeptId(reportQry.getDeptId());

        if (qry.getOtherConditions() == null) {
            qry.setOtherConditions(new HashMap<>());
        }
        qry.getOtherConditions().put(code, policyIds);
        String sql = SqlUtils.buildSql(qry, "ads_res_policy_sales");

        List<Map> dataMap = jdbcService.selectList(sql, new Object[]{});

        dataMap = selectPolicyInventoryData(qry, code, dataMap, dateList);

        chart = digestibilityChart(index, code, name, dataMap, finalMaps, dateList, reportQry.getDateType().getValue(), qtyTotalMap);

        return chart;
    }

    /**
     * 设置售罄率查询的SQL条件
     * 根据不同的维度类型和筛选参数，构建对应的查询条件
     * <p>
     * 支持的筛选条件：
     * - 产品季节类型（是否过季）
     * - 产品季节
     * - 产品编码
     * - 产品级别
     * - 是否主推
     * - 品牌筛选
     * <p>
     * 支持的维度：
     * - DIGESTIBILITY_CATEGORY: 品类维度
     * - DIGESTIBILITY_ASSORTMENT: 品类组合维度
     * - DIGESTIBILITY_STYLE: 款式维度
     *
     * @param params      查询参数列表，包含各种筛选条件
     * @param qry         数据查询对象，用于设置SQL条件
     * @param dimensionId 维度ID，决定查询的产品维度类型
     */
    private void setDigestibilitySqlQry(List<ParamQry> params, DimensionDataGroupQry qry, Long dimensionId) {
        String prodType = params.stream().filter(item -> ParamType.OUT_SEASON.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
        String prodSeason = params.stream().filter(item -> ParamType.SEASON.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
        String prodCode = params.stream().filter(item -> ParamType.CODE.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
        String prodLevel = params.stream().filter(item -> ParamType.LEVEL.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
        String isMainly = params.stream().filter(item -> ParamType.IS_MAINLY.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
        String[] bands = params.stream().filter(item -> ParamType.BAND.getValue().equals(item.getType())).findFirst().map(ParamQry::getCodes).orElse(null);

        Map<String, Object> other = new HashMap<>();
        if (prodType != null && !prodType.isEmpty()) {
            other.put(PROD_SEASON_FIELD, prodType);
        }

        // 品类维度处理 - 调用 ProductCategoryRemoteService
        // 设置 CATEGORY_CODE_FIELD 条件
        if (DIGESTIBILITY_CATEGORY.equals(dimensionId)) {
            if (StringUtil.isNotEmpty(prodCode)) {
                ProductCategoryListQry prodQry = new ProductCategoryListQry();
                List<String> stringIds = Arrays.asList(prodCode.split(","));
                List<Long> ids = stringIds.stream()
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
                prodQry.setIds(ids);
                Response<List<ProductCategoryVO>> res = productCategoryRemoteService.selectList(prodQry);
                if (!res.isSuccess()) {
                    return;
                }
                List<String> codes = res.get().stream().map(ProductCategoryVO::getCode).toList();
                other.put(CATEGORY_CODE_FIELD, codes);
            }

        } else if (DIGESTIBILITY_ASSORTMENT.equals(dimensionId)) {
            // 品种维度处理 - 调用 ProductAssortmentRemoteService
            // 设置 ASSORTMENT_CODE_FIELD 条件

            if (StringUtil.isNotEmpty(prodCode)) {
                ProductAssortmentListQry prodQry = new ProductAssortmentListQry();
                List<String> stringIds = Arrays.asList(prodCode.split(","));
                List<Long> ids = stringIds.stream()
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
                prodQry.setIds(ids);
                Response<List<ProductAssortmentVO>> res = productAssortmentRemoteService.selectList(prodQry);
                if (!res.isSuccess()) {
                    return;
                }

                List<String> codes = res.get().stream()
                        .map(ProductAssortmentVO::getCode).toList();

                other.put(ASSORTMENT_CODE_FIELD, codes);
            }

        } else if (DIGESTIBILITY_STYLE.equals(dimensionId)) {
            // 款式维度处理 - 调用 ProductStyleRemoteService
            // 支持更多筛选条件：季节、是否主推、级别、品牌等
            // 设置 STYLE_CODE_FIELD 条件
            if (StringUtil.isNotEmpty(prodSeason) || StringUtil.isNotEmpty(isMainly) || StringUtil.isNotEmpty(prodLevel) || StringUtil.isNotEmpty(prodCode)
                    || (bands != null && bands.length > 0)) {

                ProductStylePageQry prodQry = new ProductStylePageQry();
                if (StringUtil.isNotEmpty(prodSeason)) {
                    prodQry.setSeason(prodSeason);
                }

                // 将是否主推改成按政策走：v.1.2.6需求
                if (StringUtil.isNotEmpty(isMainly)) {
                    prodQry.setPromotionTiming(isMainly);
                }

                if (StringUtil.isNotEmpty(prodLevel)) {
                    prodQry.setLevel(prodLevel);
                }

                // 波段处理
                if (bands != null && bands.length > 0) {
                    List<Long> bandIds = Arrays.stream(bands)
                            .filter(StringUtil::isNotEmpty)
                            .map(String::trim)
                            .map(band -> {
                                try {
                                    return Long.valueOf(band);
                                } catch (NumberFormatException e) {
                                    return null;
                                }
                            })
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());

                    if (!bandIds.isEmpty()) {
                        prodQry.setBandIds(bandIds);
                    }
                }

                List<String> stringIds = new ArrayList<>();
                if (StringUtil.isNotEmpty(prodCode)) {
                    stringIds = Arrays.asList(prodCode.split(","));
                    List<Long> ids = stringIds.stream()
                            .map(Long::parseLong)
                            .collect(Collectors.toList());
                    prodQry.setIds(ids);
                }

                Response<List<ProductStyleQueryVO>> res = productStyleRemoteService.selectList(prodQry);
                if (!res.isSuccess()) {
                    return;
                }

                List<String> codes = res.get().stream()
                        .map(ProductStyleQueryVO::getCode).collect(Collectors.toList());

                other.put(STYLE_CODE_FIELD, codes);
            }
        }

        qry.setOtherConditions(other);
    }

    /**
     * 获取查询范围外的前期销量数据（仅周维度使用）
     * <p>
     * 业务背景：
     * 在周维度查询中，售罄率需要包含从年初到查询开始前的累计销量
     * 例如：查询第10周的售罄率，需要包含第1-9周的累计销量
     * <p>
     * 计算逻辑：
     * 1. 判断查询开始周是否为年度第一周
     * 2. 如果不是第一周，则查询从年初第一周到查询开始前一周的累计销量
     * 3. 这些前期销量会累加到当期销量中用于售罄率计算
     *
     * @param deptId    部门ID，用于数据权限控制
     * @param startDate 查询开始日期（周格式）
     * @param qry       原查询条件，复用其筛选条件
     * @return List<Map> 前期累计销量数据，按产品维度分组
     */
    public List<Map> getBeforeQty(Long deptId, String startDate, DimensionDataGroupQry qry) {

        String firstWeek = startDate.substring(0, 4) + "-01";
        String startWeek = DateUtils.getWeek(startDate);
        if (!startWeek.equals(firstWeek)) {
            List<String> groupBy = new ArrayList<>(qry.getGroupBy());
            if (groupBy.size() == 1 && groupBy.getFirst().equals(DATE_FIELD)) {
                groupBy = null;
            } else {
                groupBy.removeIf(s -> s.equals(DATE_FIELD));
            }

            DimensionDataGroupQry qtyQry = new DimensionDataGroupQry()
                    .setDeptId(deptId)
                    .setDateType(TYPE_WEEK)
                    .setStartDate(DateUtils.getWeekFirstDay(firstWeek))
                    .setEndDate(DateUtils.getWeekFirstDay(DateUtils.getLastWeek(startWeek)))
                    .setGroupFields(Collections.singletonList(new GroupField().setFieldName(QTY_FIELD).setGroupType("sum")))
                    .setGroupBy(groupBy)
                    .setOtherConditions(qry.getOtherConditions() != null ? qry.getOtherConditions() : new HashMap<>());

            String sql = SqlUtils.buildSql(qtyQry, "ads_base_product_multi_sales");

            return jdbcService.selectList(sql, new Object[]{});
        } else {
            return new ArrayList<>();
        }
    }

    private Chart<List<List<Object>>> digestibilityChart(IndexVO index, String key, String mainIndex, List<Map> dataMap, List<Map> finalMaps, List<String> dateList, String dateType, List<Map> qtyMaps) {

        String field = HumpUtil.hump2underline(index.getFieldName());
        Chart<List<List<Object>>> chart = new Chart<>();
        List<List<Object>> total = new ArrayList<>();
        List<List<Object>> datas = new ArrayList<>();

        Map<String, BigDecimal> qtyMap = new HashMap<>();

        for (Map map : finalMaps) {
            if (index.getId().equals(DIGESTIBILITY_INDEX_ID)) {
                total.add(Arrays.asList(map.get(mainIndex) == null ? "其他" : ("null".equals(map.get(mainIndex)) ? "其他" : (String) map.get(mainIndex)),
                        map.get(field) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : map.get(field) + "%",
                        null,
                        0));
            } else {
                total.add(Arrays.asList(map.get(mainIndex) == null ? "其他" : ("null".equals(map.get(mainIndex)) ? "其他" : (String) map.get(mainIndex)),
                        map.get(field) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : map.get(field),
                        null,
                        0));
            }

            chart.getItems().add(map.get(mainIndex) == null ? "其他" : ("null".equals(map.get(mainIndex)) ? "其他" : (String) map.get(mainIndex)));

            Map qm = qtyMaps.stream()
                    .filter(m -> Objects.equals(m.get(key), map.get(key)))
                    .findAny().orElse(new HashMap());

            qtyMap.put(String.valueOf(map.get(key)), (BigDecimal) qm.get(QTY_FIELD));
        }


        for (String date : dateList) {
            List<Object> row = new ArrayList<>();
            row.add(DateUtils.getReportDateName(date, dateType));
            for (Map map : finalMaps) {
                Map data = dataMap.stream()
                        .filter(m -> Objects.equals(m.get(key), map.get(key)))
                        .filter(m -> Objects.equals(m.get(DATE_FIELD), date))
                        .findAny().orElse(new HashMap());

                BigDecimal value;
                if (index.getId().equals(DIGESTIBILITY_INDEX_ID)) {
                    BigDecimal inventory = data.get(INVENTORY_FIELD) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) data.get(INVENTORY_FIELD);
                    BigDecimal qty = data.get(QTY_FIELD) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) data.get(QTY_FIELD);

                    BigDecimal totalQty = qty.add(qtyMap.get(String.valueOf(map.get(key))) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : qtyMap.get(String.valueOf(map.get(key))));

                    qtyMap.put(String.valueOf(map.get(key)), totalQty);

                    if (totalQty.doubleValue() + inventory.doubleValue() > 0 && totalQty.doubleValue() > 0) {
                        value = totalQty.multiply(BigDecimal.valueOf(100)).divide(totalQty.add(inventory), 2, RoundingMode.HALF_UP);
                    } else {
                        value = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
                    }
                } else {
                    value = data.get(field) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) data.get(field);
                }

                row.add(value);
            }
            datas.add(row);
        }

        chart.setDatas(datas);
        chart.setExtend(total);

        return chart;
    }

    /**
     * 获取商品售罄率表格数据
     * 售罄率 = (累计销量) ÷ (累计销量 + 库存) × 100%
     * <p>
     * 业务流程：
     * 1. 构建查询条件和分组字段
     * 2. 查询销量、库存等基础数据
     * 3. 处理周维度的前期数量累计
     * 4. 计算各产品的售罄率并排序
     * 5. 分页处理并构建表格数据
     * 6. 返回包含明细和合计的分页表格
     *
     * @param reportQry 表格查询参数，包含时间范围、维度、分页等信息
     * @return DatatablePage 分页表格数据，包含售罄率明细和汇总
     */
    public DatatablePage digestibilityDimensionTable(TableReportQry reportQry) {
        Integer categoryLevel = convertCategoryLevel(reportQry.getCategoryLevel());

        if (categoryLevel == null || categoryLevel == 0) {
            // 原有逻辑：使用ads_base_product_multi_sales表
            return digestibilityDimensionTableOriginal(reportQry);
        }
        // 新逻辑：使用ads_res_policy_sales和ads_res_policy_inventory表
        else if (categoryLevel >= 1 && categoryLevel <= 7) {
            return digestibilityDimensionTablePolicy(reportQry);
        } else {
            throw new IllegalArgumentException("不支持的商品分类等级值: " + categoryLevel);
        }
    }

    /**
     * 【原有逻辑】获取商品售罄率表格数据 - 使用ads_base_product_multi_sales表
     * 售罄率 = (累计销量) ÷ (累计销量 + 库存) × 100%
     */
    private DatatablePage digestibilityDimensionTableOriginal(TableReportQry reportQry) {
        // 【节点1】提取查询参数 - 获取部门ID用于数据权限控制
        Long deptId = reportQry.getDeptId();

        DatatablePage table = new DatatablePage();
        List<RowData> data = new ArrayList<>();

        // 【节点2】分页参数处理 - 确定当前页码和页面大小
        int pageNum = reportQry.getPageNum();
        int pageSize = reportQry.getPageSize();

        // 【节点3】维度处理 - 根据维度ID获取对应的编码和名称字段
        List<String> groupBy = new ArrayList<>();
        List<String> codeName = getProdCodeAndName(DIGESTIBILITY_STYLE);
        String code = codeName.getFirst();
        String name = codeName.getLast();
        groupBy.add(code);
        groupBy.add(name);

        // 【节点4】聚合字段定义 - 定义需要汇总的销量字段
        List<GroupField> groupFields = new ArrayList<>(Arrays.asList(
                new GroupField().setFieldName(QTY_FIELD).setGroupType("sum"),                              // 总数量
                new GroupField().setFieldName(POSITIVE_SALES_VOLUME_FIELD_NAME).setGroupType("sum"),       // 正销量
                new GroupField().setFieldName(SPECIAL_SALES_VOLUME_FIELD_NAME).setGroupType("sum")         // 特殊销量
        ));

        // 【节点5】时间范围处理 - 获取查询时间范围内的所有日期列表
        List<String> dateList = DateUtils.getHistoryDateList(reportQry.getStartDate(), reportQry.getEndDate(), reportQry.getDateType().getValue(), DELAY);
        if (dateList.isEmpty()) {
            return table;
        }

        String startDate = dateList.getFirst();
        String endDate = dateList.getLast();

        // 【节点6】表格标题构建 - 动态生成包含日期的表头
        List<Title> titles = new ArrayList<>();
        titles.add(new Title().setName("名称").setCode("name"));
        titles.addAll(ETLUtils.getTitles(dateList, reportQry.getDateType().getValue()));
        titles.add(new Title().setName("累计").setCode("avg"));

        // 【节点7】基础查询条件构建 - 构建Doris数据查询条件
        DimensionDataGroupQry qry = new DimensionDataGroupQry()
                .setSalesType(reportQry.getSalesType())
                .setDeptId(reportQry.getDeptId())
                .setDateType(reportQry.getDateType().getValue())
                .setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupFields(groupFields)
                .setGroupBy(groupBy);

        // 【关键业务节点】设置售罄率特定的查询条件（产品筛选、季节、品牌等）
        setDigestibilitySqlQry(reportQry.getParams(), qry, DIGESTIBILITY_STYLE);

        // 【节点8】查询基础销量数据 - 从ads_base_product_multi_sales表查询销量数据
        String sql = SqlUtils.buildSql(qry, "ads_base_product_multi_sales");
        List<Map> maps = jdbcService.selectList(sql, new Object[]{});

        // 【关键业务节点】周维度前期数量处理 - 查询查询范围外的累计销量（仅周维度需要）
        List<Map> qtyMaps = new ArrayList<>();
        if (TYPE_WEEK.equals(reportQry.getDateType().getValue())) {
            qtyMaps = getBeforeQty(deptId, startDate, qry);
        }

        // 【节点9】库存基准时间获取 - 获取查询范围内最大的库存时间作为计算基准
        String s = productDataQueryExe.selectMaxInventoryDate(startDate, endDate, reportQry.getDateType().getValue());

        // 【节点10】库存数据查询 - 查询各产品的库存数据
        List<Map> lastMap = productDataQueryExe.selectInventoryData(qry, code, new ArrayList<>());

        // 【节点11】总销量数据查询 - 按时间维度查询总销量，用于合计行计算
        qry.setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupBy(List.of(DATE_FIELD))
                .setDeptId(deptId);

        String totalSql = SqlUtils.buildSql(qry, "ads_base_product_multi_sales");
        List<Map> total = jdbcService.selectList(totalSql, new Object[]{});

        total = productDataQueryExe.selectInventoryData(qry, null, total, dateList);

        // 【关键业务节点】售罄率计算和排序 - 计算各产品售罄率并按售罄率倒序排列
        List<Map> res = digestibilitySummarize(code, maps, lastMap, qtyMaps);

        int totalSize = res.size() + 1;

        List<Map> finalMaps;

        // 【关键业务节点】合计行数据构建 - 构建汇总所有产品的合计行数据
        RowData totalItem = digestibilityTotalData(total, dateList, s, qtyMaps);

        // 【节点12】分页逻辑处理 - 第一页包含合计行，其他页面不包含
        if (pageNum == 1) {
            finalMaps = res.subList(0, Math.min(res.size(), pageSize - 1));
            data.add(totalItem);  // 第一页添加合计行
        } else {
            finalMaps = res.subList(
                    Math.min(res.size(), (pageNum - 1) * pageSize - 1),
                    Math.min(res.size(), pageNum * pageSize - 1)
            );
        }

        // 【节点13】当页明细数据查询 - 查询当前页面产品的详细销量和库存数据
        List<String> codes = finalMaps.stream()
                .map(m -> (String) m.get(code))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        groupBy.add(DATE_FIELD);

        qry.setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupBy(groupBy)
                .setDeptId(deptId);

        if (qry.getOtherConditions() == null) {
            qry.setOtherConditions(new HashMap<>());
        }
        qry.getOtherConditions().put(code, codes);

        String dataSql = SqlUtils.buildSql(qry, "ads_base_product_multi_sales");
        List<Map> dataMap = jdbcService.selectList(dataSql, new Object[]{});

        dataMap = productDataQueryExe.selectInventoryData(qry, code, dataMap, dateList);

        // 【关键业务节点】明细数据构建 - 为每个产品构建包含售罄率的详细行数据
        data.addAll(digestibilityData(name, code, finalMaps, dataMap, dateList, qtyMaps));

        // 【节点14】表格数据组装 - 组装最终的分页表格数据
        table.setDatas(data);
        table.setTitles(titles);
        table.setSize(pageSize);
        table.setCurrent(pageNum);
        table.setTotal(totalSize);

        return table;
    }

    /**
     * 【新逻辑】获取政策售罄率表格数据 - 使用ads_res_policy_sales表
     * 售罄率 = (累计销量) ÷ (累计销量 + 库存) × 100%
     */
    private DatatablePage digestibilityDimensionTablePolicy(TableReportQry reportQry) {
        // 【节点1】提取查询参数
        Long deptId = reportQry.getDeptId();
        Integer categoryLevel = convertCategoryLevel(reportQry.getCategoryLevel());

        DatatablePage table = new DatatablePage();
        List<RowData> data = new ArrayList<>();

        // 【节点2】分页参数处理
        int pageNum = reportQry.getPageNum();
        int pageSize = reportQry.getPageSize();

        // 【节点3】政策维度处理 - 使用policy_id和policy_name字段
        List<String> groupBy = new ArrayList<>();
        String code = "policy_id";          // 政策ID字段
        String name = "policy_name";        // 政策名称字段
        groupBy.add(code);
        groupBy.add(name);

        // 【节点4】聚合字段定义
        List<GroupField> groupFields = new ArrayList<>(Arrays.asList(
                new GroupField().setFieldName(QTY_FIELD).setGroupType("sum"),                              // 总销量
                new GroupField().setFieldName(POSITIVE_SALES_VOLUME_FIELD_NAME).setGroupType("sum"),       // 正销量
                new GroupField().setFieldName(SPECIAL_SALES_VOLUME_FIELD_NAME).setGroupType("sum")         // 特价销量
        ));

        // 【节点5】时间范围处理
        List<String> dateList = DateUtils.getHistoryDateList(reportQry.getStartDate(), reportQry.getEndDate(), reportQry.getDateType().getValue(), DELAY);
        if (dateList.isEmpty()) {
            return table;
        }

        String startDate = dateList.getFirst();
        String endDate = dateList.getLast();

        // 【节点6】表格标题构建
        List<Title> titles = new ArrayList<>();
        titles.add(new Title().setName("名称").setCode("name"));
        titles.addAll(ETLUtils.getTitles(dateList, reportQry.getDateType().getValue()));
        titles.add(new Title().setName("累计").setCode("avg"));

        // 【节点7】基础查询条件构建 - 使用新表ads_res_policy_sales
        DimensionDataGroupQry qry = new DimensionDataGroupQry()
                .setOrgNo(UserHolder.getLoginUser().getOrgNo())
                .setSalesType(reportQry.getSalesType())
                .setDeptId(reportQry.getDeptId())
                .setDateType(reportQry.getDateType().getValue())
                .setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupFields(groupFields)
                .setGroupBy(groupBy);

        // 【新逻辑】设置政策层级条件
        Map<String, Object> otherConditions = new HashMap<>();
        otherConditions.put("level", categoryLevel);  // 根据categoryLevel设置level条件

        // 【适配原有筛选条件】处理原有的筛选条件
        setPolicyDigestibilitySqlQry(reportQry.getParams(), otherConditions, categoryLevel);
        qry.setOtherConditions(otherConditions);

        // 【节点8】查询政策销量数据 - 从ads_res_policy_sales表查询
        String sql = SqlUtils.buildSql(qry, "ads_res_policy_sales");
        List<Map> maps = jdbcService.selectList(sql, new Object[]{});

        // 【关键业务节点】周维度前期数量处理（政策表）
        List<Map> qtyMaps = new ArrayList<>();
        if (TYPE_WEEK.equals(reportQry.getDateType().getValue())) {
            qtyMaps = getBeforeQtyPolicy(deptId, startDate, qry, categoryLevel);
        }

        // 【节点9】库存基准时间获取
        String maxInventoryDate = selectMaxInventoryDatePolicy(startDate, endDate, reportQry.getDateType().getValue());

        // 【节点10】政策库存数据查询 - 查询政策库存数据
        List<Map> lastMap = selectPolicyInventoryData(qry, code, new ArrayList<>());

        // 【节点11】总销量数据查询 - 按时间维度查询政策总销量
        qry.setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupBy(List.of(DATE_FIELD))
                .setDeptId(deptId);

        String totalSql = SqlUtils.buildSql(qry, "ads_res_policy_sales");
        List<Map> total = jdbcService.selectList(totalSql, new Object[]{});

        total = selectPolicyInventoryData(qry, null, total, dateList);

        // 【关键业务节点】售罄率计算和排序
        List<Map> res = digestibilitySummarize(code, maps, lastMap, qtyMaps);

        int totalSize = res.size() + 1;

        List<Map> finalMaps;

        // 【关键业务节点】合计行数据构建
        RowData totalItem = digestibilityTotalData(total, dateList, maxInventoryDate, qtyMaps);

        // 【节点12】分页逻辑处理
        if (pageNum == 1) {
            finalMaps = res.subList(0, Math.min(res.size(), pageSize - 1));
            data.add(totalItem);
        } else {
            finalMaps = res.subList(
                    Math.min(res.size(), (pageNum - 1) * pageSize - 1),
                    Math.min(res.size(), pageNum * pageSize - 1)
            );
        }

        // 【节点13】当页明细数据查询 - 查询当前页面政策的详细销量和库存数据
        List<Long> policyIds = finalMaps.stream()
                .map(m -> (Long) m.get(code))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        groupBy.add(DATE_FIELD);

        qry.setStartDate(startDate)
                .setEndDate(endDate)
                .setGroupBy(groupBy)
                .setDeptId(deptId);

        if (qry.getOtherConditions() == null) {
            qry.setOtherConditions(new HashMap<>());
        }
        qry.getOtherConditions().put(code, policyIds);

        String dataSql = SqlUtils.buildSql(qry, "ads_res_policy_sales");
        List<Map> dataMap = jdbcService.selectList(dataSql, new Object[]{});

        dataMap = selectPolicyInventoryData(qry, code, dataMap, dateList);

        // 【关键业务节点】明细数据构建
        data.addAll(digestibilityData(name, code, finalMaps, dataMap, dateList, qtyMaps));

        // 【节点14】表格数据组装
        table.setDatas(data);
        table.setTitles(titles);
        table.setSize(pageSize);
        table.setCurrent(pageNum);
        table.setTotal(totalSize);

        return table;
    }

    /**
     * 设置政策售罄率查询的SQL条件
     * 适配原有的筛选条件到新的政策表结构
     *
     * @param params          查询参数列表
     * @param otherConditions 其他查询条件
     * @param categoryLevel   商品分类等级
     */
    private void setPolicyDigestibilitySqlQry(List<ParamQry> params, Map<String, Object> otherConditions, Integer categoryLevel) {

        // 产品编码(也就是款式)筛选 - 政策表结构不同，使用policy_id进行筛选，policy_id=品种/品类/款式的 id
        String prodCode = params.stream().filter(item -> ParamType.CODE.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
        String[] bands = params.stream().filter(item -> ParamType.BAND.getValue().equals(item.getType())).findFirst().map(ParamQry::getCodes).orElse(null);

        if (StringUtil.isNotEmpty(prodCode)) {
            // 优先处理产品编码
            List<String> stringIds = Arrays.asList(prodCode.split(","));
            List<Long> ids = stringIds.stream()
                    .map(Long::parseLong)
                    .collect(Collectors.toList());
            otherConditions.put("policy_id", ids);
        } else if (bands != null && bands.length > 0) {
            // 如果产品编码为空，处理波段筛选 - 通过RPC接口查询对应的policy_id
            List<Long> bandIds = Arrays.stream(bands)
                    .map(Long::parseLong)
                    .collect(Collectors.toList());
            
            // 调用RPC接口查询对应的policy_id
            PolicyDetailByLevelBandQry policyQry = new PolicyDetailByLevelBandQry();
            policyQry.setLevel(categoryLevel);
            policyQry.setBandIds(bandIds);
            
            Response<List<Long>> response = policyDetailRemoteService.selectPolicyForStyle(policyQry);
            if (response.isSuccess() && response.getData() != null && !response.getData().isEmpty()) {
                otherConditions.put("policy_id", response.getData());
            }
        }

        // 保留：过应季季节筛选 - 政策表中没有对应字段，暂时保留
        String prodType = params.stream().filter(item -> ParamType.OUT_SEASON.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
        // 保留：季节筛选
        String prodSeason = params.stream().filter(item -> ParamType.SEASON.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
        // 保留：产品级别筛选
        String prodLevel = params.stream().filter(item -> ParamType.LEVEL.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
        // 保留：是否主推筛选
        String isMainly = params.stream().filter(item -> ParamType.IS_MAINLY.getValue().equals(item.getType())).findFirst().map(ParamQry::getCode).orElse(null);
    }

    /**
     * 获取政策查询范围外的前期销量数据（仅周维度使用）
     */
    public List<Map> getBeforeQtyPolicy(Long deptId, String startDate, DimensionDataGroupQry qry, Integer categoryLevel) {
        String firstWeek = startDate.substring(0, 4) + "-01";
        String startWeek = DateUtils.getWeek(startDate);
        if (!startWeek.equals(firstWeek)) {
            List<String> groupBy = new ArrayList<>(qry.getGroupBy());
            if (groupBy.size() == 1 && groupBy.getFirst().equals(DATE_FIELD)) {
                groupBy = null;
            } else {
                groupBy.removeIf(s -> s.equals(DATE_FIELD));
            }

            DimensionDataGroupQry qtyQry = new DimensionDataGroupQry()
                    .setOrgNo(UserHolder.getLoginUser().getOrgNo())
                    .setDeptId(deptId)
                    .setDateType(TYPE_WEEK)
                    .setStartDate(DateUtils.getWeekFirstDay(firstWeek))
                    .setEndDate(DateUtils.getWeekFirstDay(DateUtils.getLastWeek(startWeek)))
                    .setGroupFields(Collections.singletonList(new GroupField().setFieldName(QTY_FIELD).setGroupType("sum")))
                    .setGroupBy(groupBy);

            // 设置level条件
            Map<String, Object> otherConditions = qry.getOtherConditions() != null ?
                    new HashMap<>(qry.getOtherConditions()) : new HashMap<>();
            otherConditions.put("level", categoryLevel);
            qtyQry.setOtherConditions(otherConditions);

            String sql = SqlUtils.buildSql(qtyQry, "ads_res_policy_sales");
            return jdbcService.selectList(sql, new Object[]{});
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * 查询政策库存数据的最大库存时间
     */
    private String selectMaxInventoryDatePolicy(String startDate, String endDate, String dateType) {
        // 构建查询最大库存日期的SQL
        String sql = "SELECT MAX(date) as max_date FROM ads_res_policy_inventory " +
                "WHERE date >= ? AND date <= ? AND date_type = ?";

        List<Map> result = jdbcService.selectList(sql, new Object[]{startDate, endDate, dateType});
        if (!result.isEmpty() && result.get(0).get("max_date") != null) {
            return (String) result.get(0).get("max_date");
        }
        return endDate; // 如果查询不到，返回结束日期
    }

    /**
     * 查询政策库存数据
     */
    private List<Map> selectPolicyInventoryData(DimensionDataGroupQry qry, String code, List<Map> data) {
        return selectPolicyInventoryData(qry, code, data, new ArrayList<>());
    }

    /**
     * 查询政策库存数据（带日期列表）
     */
    private List<Map> selectPolicyInventoryData(DimensionDataGroupQry qry, String code, List<Map> data, List<String> dateList) {
        // 修正分组逻辑：确保始终包含日期字段
        List<String> groupBy = new ArrayList<>();
        if (code != null) {
            groupBy.add(code);
        }
        groupBy.add(DATE_FIELD);  // 始终包含日期字段

        // 设置查询类并查询政策库存表
        DimensionDataGroupQry inventoryQry = new DimensionDataGroupQry()
                .setOrgNo(qry.getOrgNo())
                .setStartDate(qry.getStartDate())
                .setEndDate(qry.getEndDate())
                .setDeptId(qry.getDeptId())
                .setDateType(qry.getDateType())
                .setGroupBy(groupBy)
                .setOtherConditions(qry.getOtherConditions() != null ? qry.getOtherConditions() : new HashMap<>());

        // 政策库存表的聚合字段（根据实际表结构调整）
        List<GroupField> inventoryGroupFields = new ArrayList<>(Arrays.asList(
                // 根据ads_res_policy_inventory表的实际字段调整
                GroupField.of("inventory", "sum")  // 假设库存字段为inventory
        ));

        inventoryQry.setGroupFields(inventoryGroupFields);

        String sql = SqlUtils.buildSql(inventoryQry, "ads_res_policy_inventory");
        List<Map> inventoryData = jdbcService.selectList(sql, new Object[]{});

        // 如果传入的data为空，直接返回库存数据（用于单个产品售罄率计算）
        if (data.isEmpty()) {
            // 将库存字段重命名为标准字段名
            for (Map inventoryMap : inventoryData) {
                inventoryMap.put(INVENTORY_FIELD, inventoryMap.get("inventory"));
            }
            return inventoryData;
        }

        // 否则执行原有的合并逻辑（用于合计行和详细数据计算）
        for (Map map : data) {
            String dateValue = (String) map.get(DATE_FIELD);
            Object codeValue = code == null ? null : map.get(code);

            for (Map inventoryMap : inventoryData) {
                boolean matched = Objects.equals(inventoryMap.get(DATE_FIELD), dateValue);
                if (code != null) {
                    matched = matched && Objects.equals(inventoryMap.get(code), codeValue);
                }

                if (matched) {
                    // 将库存数据合并到销量数据中
                    map.put(INVENTORY_FIELD, inventoryMap.get("inventory"));
                    break;
                }
            }
        }

        return data;
    }

    /**
     * 按产品汇总数据，避免同一产品出现多条记录
     * 
     * @param key 产品关键字段（如style_code）
     * @param maps 原始数据（可能同一产品有多条时间记录）
     * @param fieldName 需要汇总的指标字段名
     * @return 按产品汇总后的数据（每个产品一条记录）
     */
    private List<Map> aggregateDataByProduct(String key, List<Map> maps, String fieldName) {
        Map<Object, Map> productDataMap = new HashMap<>();
        
        for (Map map : maps) {
            Object productKey = map.get(key);
            if (productKey == null) continue;
            
            Map existingData = productDataMap.get(productKey);
            if (existingData == null) {
                // 第一次遇到这个产品，直接保存
                Map newData = new HashMap(map);
                productDataMap.put(productKey, newData);
            } else {
                // 已存在该产品，需要汇总数值字段
                aggregateNumericFields(existingData, map);
            }
        }
        
        return new ArrayList<>(productDataMap.values());
    }
    
    /**
     * 汇总数值字段
     */
    private void aggregateNumericFields(Map existingData, Map newData) {
        // 汇总销量相关字段
        aggregateField(existingData, newData, QTY_FIELD);
        aggregateField(existingData, newData, POSITIVE_SALES_VOLUME_FIELD_NAME);
        aggregateField(existingData, newData, SPECIAL_SALES_VOLUME_FIELD_NAME);
        // 可以根据需要添加其他数值字段的汇总
    }
    
    /**
     * 汇总单个字段
     */
    private void aggregateField(Map existingData, Map newData, String fieldName) {
        BigDecimal existingValue = (BigDecimal) existingData.get(fieldName);
        BigDecimal newValue = (BigDecimal) newData.get(fieldName);
        
        if (existingValue == null) existingValue = BigDecimal.ZERO;
        if (newValue == null) newValue = BigDecimal.ZERO;
        
        existingData.put(fieldName, existingValue.add(newValue));
    }

    /**
     * 【核心业务方法】计算各产品的售罄率并排序
     * <p>
     * 售罄率计算公式：
     * 售罄率 = (当期销量 + 前期销量) × 100 ÷ (当期销量 + 前期销量 + 库存)
     * <p>
     * 处理流程：
     * 1. 遍历每个产品的销量数据
     * 2. 匹配对应的库存数据和前期销量数据
     * 3. 按公式计算售罄率（保留2位小数）
     * 4. 对计算结果按售罄率从高到低排序
     * <p>
     * 特殊处理：
     * - 当分母为0或累计销量为0时，售罄率设为null
     * - 使用HALF_UP舍入模式确保计算精度
     *
     * @param key           产品维度的关键字段（如款式编码、品类编码等）
     * @param maps          当期销量数据列表
     * @param inventoryMaps 库存数据列表
     * @param qtyMaps       前期销量数据列表（周维度专用）
     * @return List<Map> 包含售罄率的产品数据，按售罄率倒序排列
     */
    private List<Map> digestibilitySummarize(String key, List<Map> maps, List<Map> inventoryMaps, List<Map> qtyMaps) {
        for (Map m : maps) {
            Map l = inventoryMaps.stream()
                    .filter(lm -> Objects.equals(lm.get(key), m.get(key)))
                    .findAny().orElse(new HashMap());

            Map qtyMap = qtyMaps.stream()
                    .filter(lm -> Objects.equals(lm.get(key), m.get(key)))
                    .findAny().orElse(new HashMap());

            BigDecimal inventory = l.get(INVENTORY_FIELD) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) l.get(INVENTORY_FIELD);
            BigDecimal qty = m.get(QTY_FIELD) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) m.get(QTY_FIELD);
            BigDecimal beforeQty = qtyMap.get(QTY_FIELD) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) qtyMap.get(QTY_FIELD);

            // 【核心计算】售罄率 = (当期销量 + 前期销量) × 100 ÷ (当期销量 + 前期销量 + 库存)
            if (qty.add(inventory).add(beforeQty).doubleValue() > 0 && qty.add(beforeQty).doubleValue() > 0) {
                // 计算公式：累计销量(当期+前期) × 100 ÷ 总量(累计销量+库存)
                m.put(DIGESTIBILITY_FIELD, qty.add(beforeQty).multiply(BigDecimal.valueOf(100)).divide(qty.add(beforeQty).add(inventory), 2, RoundingMode.HALF_UP));
            } else {
                // 当总量为0或累计销量为0时，售罄率设为null
                m.put(DIGESTIBILITY_FIELD, null);
            }
        }

        maps.sort(Comparator.comparing((Map a) -> (a.get(DIGESTIBILITY_FIELD) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) a.get(DIGESTIBILITY_FIELD))).reversed());

        return maps;
    }

    /**
     * 构建售罄率表格的明细数据行
     * <p>
     * 数据结构：
     * 每个产品构建一个主行 + 3个子行的层级结构
     * - 主行：显示产品名称和每日售罄率
     * - 子行1：总数量明细
     * - 子行2：正销量明细
     * - 子行3：特殊销量明细
     * <p>
     * 处理逻辑：
     * 1. 为每个产品创建主行和子行数据结构
     * 2. 按日期循环计算每日的售罄率和销量数据
     * 3. 累计前期销量用于售罄率计算（仅周维度）
     * 4. 设置累计列数据（查询期间的汇总值）
     *
     * @param mainIndex 产品名称字段
     * @param key       产品编码字段
     * @param items     当前页的产品列表（已排序）
     * @param data      详细的销量和库存数据
     * @param dates     日期列表
     * @param qtyMaps   前期销量数据（周维度专用）
     * @return List<RowData> 表格行数据，包含主行和子行结构
     */
    private List<RowData> digestibilityData(String mainIndex, String key, List<Map> items, List<Map> data, List<String> dates, List<Map> qtyMaps) {

        List<RowData> res = new ArrayList<>();

        for (Map item : items) {
            RowData dataMap = new RowData();
            List<RowData> children = new ArrayList<>();

            RowData m1 = new RowData();
            RowData m2 = new RowData();
            RowData m3 = new RowData();

            dataMap.put("name", item.get(mainIndex) == null ? "其他" : ("null".equals(item.get(mainIndex)) ? "其他" : (String) item.get(mainIndex)));
            dataMap.put("index", DIGESTIBILITY_INDEX_NAME);

            m1.put("name", TOTAL_QTY_INDEX_NAME);
            m2.put("name", POSITIVE_SALES_VOLUME_INDEX_NAME);
            m3.put("name", SPECIAL_SALES_VOLUME_INDEX_NAME);


            Double digestibilityQty = qtyMaps.stream()
                    .filter(m -> Objects.equals(m.get(key), item.get(key)))
                    .map(m -> (BigDecimal) m.get(QTY_FIELD))
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal::add)
                    .orElse(BigDecimal.ZERO)
                    .doubleValue();
            ;

            for (String date : dates) {
                List<Map> maps = data.stream()
                        .filter(m -> Objects.equals(m.get(DATE_FIELD), date) && Objects.equals(m.get(key), item.get(key)))
                        .collect(Collectors.toList());

                Double qty = maps.stream()
                        .map(m -> (BigDecimal) m.get(QTY_FIELD))
                        .filter(Objects::nonNull)
                        .mapToDouble(BigDecimal::doubleValue)
                        .sum();

                digestibilityQty += qty;


                Double inventory = maps.stream()
                        .map(m -> (BigDecimal) m.get(INVENTORY_FIELD))
                        .filter(Objects::nonNull)
                        .mapToDouble(BigDecimal::doubleValue)
                        .sum();

                Double positiveSalesVolume = maps.stream()
                        .map(m -> (BigDecimal) m.get(POSITIVE_SALES_VOLUME_FIELD_NAME))
                        .filter(Objects::nonNull)
                        .mapToDouble(BigDecimal::doubleValue)
                        .sum();

                Double specialSalesVolume = maps.stream()
                        .map(m -> (BigDecimal) m.get(SPECIAL_SALES_VOLUME_FIELD_NAME))
                        .filter(Objects::nonNull)
                        .mapToDouble(BigDecimal::doubleValue)
                        .sum();

                // 【每日售罄率计算】累计销量 ÷ (累计销量 + 当日库存) × 100%
                if (inventory + digestibilityQty > 0 && digestibilityQty > 0) {
                    // digestibilityQty为累计销量（包含前期+当日），inventory为当日库存
                    dataMap.put(date, BigDecimal.valueOf(digestibilityQty / (inventory + digestibilityQty) * 100).setScale(2, RoundingMode.HALF_UP) + "%");
                } else {
                    dataMap.put(date, null);  // 当累计销量为0或总量为0时，售罄率为空
                }
                m1.put(date, qty == 0 ? null : BigDecimal.valueOf(qty).setScale(2, RoundingMode.HALF_UP) + "");
                m2.put(date, positiveSalesVolume == 0 ? null : BigDecimal.valueOf(positiveSalesVolume).setScale(2, RoundingMode.HALF_UP) + "");
                m3.put(date, specialSalesVolume == 0 ? null : BigDecimal.valueOf(specialSalesVolume).setScale(2, RoundingMode.HALF_UP) + "");
            }

            dataMap.put("avg", item.get(DIGESTIBILITY_FIELD) == null ? null : item.get(DIGESTIBILITY_FIELD) + "%");
            m1.put("avg", item.get(QTY_FIELD) == null ? null : item.get(QTY_FIELD) + "");
            m2.put("avg", item.get(POSITIVE_SALES_VOLUME_FIELD_NAME) == null ? null : item.get(POSITIVE_SALES_VOLUME_FIELD_NAME) + "");
            m3.put("avg", item.get(SPECIAL_SALES_VOLUME_FIELD_NAME) == null ? null : item.get(SPECIAL_SALES_VOLUME_FIELD_NAME) + "");


            children.add(m1);
            children.add(m2);
            children.add(m3);

            dataMap.setChildren(children);

            res.add(dataMap);
        }

        return res;
    }

    /**
     * 构建售罄率表格的合计行数据
     * <p>
     * 合计行结构：
     * - 主行：显示"合计"标识和每日汇总售罄率
     * - 子行1：总数量汇总
     * - 子行2：正销量汇总
     * - 子行3：特殊销量汇总
     * <p>
     * 计算逻辑：
     * 1. 按日期汇总所有产品的销量数据
     * 2. 累计前期销量（周维度专用）
     * 3. 按日计算汇总售罄率：累计销量 ÷ (累计销量 + 当日库存)
     * 4. 计算整体累计售罄率：总累计销量 ÷ (总累计销量 + 最终库存)
     *
     * @param data      按时间维度的汇总数据
     * @param dates     日期列表
     * @param finalDate 最终库存基准日期
     * @param qtyMaps   前期销量数据（周维度专用）
     * @return RowData 合计行数据，包含主行和子行结构
     */
    private RowData digestibilityTotalData(List<Map> data, List<String> dates, String finalDate, List<Map> qtyMaps) {

        RowData dataMap = new RowData();
        List<RowData> children = new ArrayList<>();

        RowData m1 = new RowData();
        RowData m2 = new RowData();
        RowData m3 = new RowData();

        dataMap.put("name", "合计");
        dataMap.put("index", DIGESTIBILITY_FIELD);

        m1.put("name", TOTAL_QTY_INDEX_NAME);
        m2.put("name", POSITIVE_SALES_VOLUME_INDEX_NAME);
        m3.put("name", SPECIAL_SALES_VOLUME_INDEX_NAME);

        double sum1 = 0;
        double sum2 = 0;
        double sum3 = 0;
        double sum4 = 0;
        double inventoryQty = 0;
        BigDecimal avg = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);

        inventoryQty += qtyMaps.stream()
                .map(d -> ((BigDecimal) d.get(QTY_FIELD)))
                .filter(Objects::nonNull)
                .reduce(BigDecimal::add)
                .orElse(BigDecimal.ZERO)
                .doubleValue();

        for (String date : dates) {
            List<Map> maps = data.stream()
                    .filter(m -> Objects.equals(m.get(DATE_FIELD), date))
                    .collect(Collectors.toList());

            Double qty = maps.stream()
                    .map(m -> (BigDecimal) m.get(QTY_FIELD))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            Double openingInventory = maps.stream()
                    .map(m -> (BigDecimal) m.get(OPENING_INVENTORY_FIELD_NAME))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            Double inventory = maps.stream()
                    .map(m -> (BigDecimal) m.get(INVENTORY_FIELD))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            Double positiveSalesVolume = maps.stream()
                    .map(m -> (BigDecimal) m.get(POSITIVE_SALES_VOLUME_FIELD_NAME))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            Double specialSalesVolume = maps.stream()
                    .map(m -> (BigDecimal) m.get(SPECIAL_SALES_VOLUME_FIELD_NAME))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            Double numberOfWarehousing = maps.stream()
                    .map(m -> (BigDecimal) m.get(NUMBER_OF_WAREHOUSING_FIELD_NAME))
                    .filter(Objects::nonNull)
                    .mapToDouble(BigDecimal::doubleValue)
                    .sum();

            sum1 += qty;
            sum2 += positiveSalesVolume;
            sum3 += specialSalesVolume;
            sum4 += numberOfWarehousing;
            inventoryQty += qty;  // 累计销量：逐日累加

            // 【合计行每日售罄率计算】汇总售罄率 = 累计销量 ÷ (累计销量 + 当日库存) × 100%
            if (inventoryQty + inventory > 0 && inventoryQty > 0) {
                // inventoryQty为所有产品的累计销量，inventory为所有产品的当日库存汇总
                dataMap.put(date, BigDecimal.valueOf(inventoryQty / (inventory + inventoryQty) * 100).setScale(2, RoundingMode.HALF_UP) + "%");
            } else {
                dataMap.put(date, null);  // 当累计销量为0或总量为0时，售罄率为空
            }

//            System.out.println("时间：" + date + ", 累计销量：" + inventoryQty + ", 库存：" + inventory + "，售罄率：" + dataMap.get(date));

            m1.put(date, qty == 0 ? null : BigDecimal.valueOf(qty).setScale(2, RoundingMode.HALF_UP) + "");
            m2.put(date, positiveSalesVolume == 0 ? null : BigDecimal.valueOf(positiveSalesVolume).setScale(2, RoundingMode.HALF_UP) + "");
            m3.put(date, specialSalesVolume == 0 ? null : BigDecimal.valueOf(specialSalesVolume).setScale(2, RoundingMode.HALF_UP) + "");
//            m4.put(date, numberOfWarehousing == 0 ? null : BigDecimal.valueOf(numberOfWarehousing).setScale(2, RoundingMode.HALF_UP) + "");
//            m5.put(date, openingInventory == 0 ? null : BigDecimal.valueOf(openingInventory).setScale(2, RoundingMode.HALF_UP) + "");
//            m6.put(date, inventory == 0 ? null : BigDecimal.valueOf(inventory).setScale(2, RoundingMode.HALF_UP) + "");
        }

        Map lm = data.stream()
                .filter(m -> finalDate.equals(m.get(DATE_FIELD)))
                .findAny()
                .orElse(new HashMap());

        Map fm = data.stream()
                .filter(m -> dates.get(0).equals(m.get(DATE_FIELD)))
                .findAny()
                .orElse(new HashMap());

        BigDecimal inventory = lm.get(INVENTORY_FIELD) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) lm.get(INVENTORY_FIELD);
        BigDecimal openingInventory = fm.get(OPENING_INVENTORY_FIELD_NAME) == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : (BigDecimal) fm.get(OPENING_INVENTORY_FIELD_NAME);

        // 【最终累计售罄率计算】整个查询期间的总体售罄率
        if (inventoryQty + inventory.doubleValue() > 0 && inventoryQty > 0) {
            // inventoryQty为整个期间的累计销量，inventory为最终库存
            dataMap.put("avg", BigDecimal.valueOf(inventoryQty * 100 / (inventoryQty + inventory.doubleValue())).setScale(2, RoundingMode.HALF_UP) + "%");
        }

        m1.put("avg", sum1 == 0 ? null : sum1 + "");
        m2.put("avg", sum2 == 0 ? null : sum2 + "");
        m3.put("avg", sum3 == 0 ? null : sum3 + "");

        children.add(m1);
        children.add(m2);
        children.add(m3);
        dataMap.setChildren(children);

        return dataMap;
    }
    
    /**
     * 根据索引ID确定排序字段名称
     * 
     * @param indexId 索引ID
     * @param defaultFieldName 默认字段名
     * @return 排序字段名称
     */
    private String getSortFieldName(Long indexId, String defaultFieldName) {
        if (QTY_INDEX_ID.equals(indexId)) {
            return QTY_FIELD;
        } else if (POSITIVE_SALES_VOLUME_INDEX_ID.equals(indexId)) {
            return POSITIVE_SALES_VOLUME_FIELD_NAME;
        } else if (SPECIAL_SALES_VOLUME_INDEX_ID.equals(indexId)) {
            return SPECIAL_SALES_VOLUME_FIELD_NAME;
        } else {
            return defaultFieldName;
        }
    }
}
